<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Periodic Noise Removing Filter</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d9/df8/tutorial_root.html">OpenCV Tutorials</a></li><li class="navelem"><a class="el" href="../../d7/da8/tutorial_table_of_content_imgproc.html">Image Processing (imgproc module)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Periodic Noise Removing Filter </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Prev Tutorial:</b> <a class="el" href="../../d4/d70/tutorial_anisotropic_image_segmentation_by_a_gst.html">Anisotropic image segmentation by a gradient structure tensor</a></p>
<table class="doxtable">
<tr>
<th align="right"></th><th align="left"></th></tr>
<tr>
<td align="right">Original author </td><td align="left">Karpushin Vladislav </td></tr>
<tr>
<td align="right">Compatibility </td><td align="left">OpenCV &gt;= 3.0 </td></tr>
</table>
<h2>Goal </h2>
<p>In this tutorial you will learn:</p>
<ul>
<li>how to remove periodic noise in the Fourier domain</li>
</ul>
<h2>Theory </h2>
<dl class="section note"><dt>Note</dt><dd>The explanation is based on the book <a class="el" href="../../d0/de3/citelist.html#CITEREF_gonzalez">[94]</a>. The image on this page is a real world image.</dd></dl>
<p>Periodic noise produces spikes in the Fourier domain that can often be detected by visual analysis.</p>
<h3>How to remove periodic noise in the Fourier domain?</h3>
<p>Periodic noise can be reduced significantly via frequency domain filtering. On this page we use a notch reject filter with an appropriate radius to completely enclose the noise spikes in the Fourier domain. The notch filter rejects frequencies in predefined neighborhoods around a center frequency. The number of notch filters is arbitrary. The shape of the notch areas can also be arbitrary (e.g. rectangular or circular). On this page we use three circular shape notch reject filters. Power spectrum densify of an image is used for the noise spike’s visual detection.</p>
<h2>Source code </h2>
<p>You can find source code in the <code>samples/cpp/tutorial_code/ImgProc/periodic_noise_removing_filter/periodic_noise_removing_filter.cpp</code> of the OpenCV source code library.</p>
<div class="fragment"><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d6/d87/imgcodecs_8hpp.html">opencv2/imgcodecs.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"><span class="keyword">using namespace </span>std;</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> fftshift(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputImg, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; outputImg);</div><div class="line"><span class="keywordtype">void</span> filter2DFreq(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputImg, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; outputImg, <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; H);</div><div class="line"><span class="keywordtype">void</span> synthesizeFilterH(<a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputOutput_H, <a class="code" href="../../db/d4e/classcv_1_1Point__.html">Point</a> center, <span class="keywordtype">int</span> radius);</div><div class="line"><span class="keywordtype">void</span> calcPSD(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputImg, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; outputImg, <span class="keywordtype">int</span> flag = 0);</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main()</div><div class="line">{</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> imgIn = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>(<span class="stringliteral">&quot;input.jpg&quot;</span>, <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a>);</div><div class="line">    <span class="keywordflow">if</span> (imgIn.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>()) <span class="comment">//check whether the image is loaded or not</span></div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;ERROR : Image cannot be loaded..!!&quot;</span> &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    imgIn.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>(imgIn, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>);</div><div class="line"></div><div class="line">    <span class="comment">// it needs to process even image only</span></div><div class="line">    <a class="code" href="../../d2/d44/classcv_1_1Rect__.html">Rect</a> roi = <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, imgIn.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> &amp; -2, imgIn.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> &amp; -2);</div><div class="line">    imgIn = imgIn(roi);</div><div class="line"></div><div class="line">    <span class="comment">// PSD calculation (start)</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> imgPSD;</div><div class="line">    calcPSD(imgIn, imgPSD);</div><div class="line">    fftshift(imgPSD, imgPSD);</div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize</a>(imgPSD, imgPSD, 0, 255, <a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa9f0c1c342a18114d47b516a88e29822e">NORM_MINMAX</a>);</div><div class="line">    <span class="comment">// PSD calculation (stop)</span></div><div class="line"></div><div class="line">    <span class="comment">//H calculation (start)</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> H = <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>(roi.<a class="code" href="../../d2/d44/classcv_1_1Rect__.html#ab0c92d80e25e22be48c0110c5200da1e">size</a>(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>(1));</div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">int</span> r = 21;</div><div class="line">    synthesizeFilterH(H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(705, 458), r);</div><div class="line">    synthesizeFilterH(H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(850, 391), r);</div><div class="line">    synthesizeFilterH(H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(993, 325), r);</div><div class="line">    <span class="comment">//H calculation (stop)</span></div><div class="line">    <span class="comment">// filtering (start)</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> imgOut;</div><div class="line">    fftshift(H, H);</div><div class="line">    filter2DFreq(imgIn, imgOut, H);</div><div class="line">    <span class="comment">// filtering (stop)</span></div><div class="line"><span class="comment"></span></div><div class="line">    imgOut.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>(imgOut, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32b18d904ee2b1731a9416a8eef67d06">CV_8U</a>);</div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize</a>(imgOut, imgOut, 0, 255, <a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa9f0c1c342a18114d47b516a88e29822e">NORM_MINMAX</a>);</div><div class="line">    <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>(<span class="stringliteral">&quot;result.jpg&quot;</span>, imgOut);</div><div class="line">    <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>(<span class="stringliteral">&quot;PSD.jpg&quot;</span>, imgPSD);</div><div class="line">    fftshift(H, H);</div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize</a>(H, H, 0, 255, <a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa9f0c1c342a18114d47b516a88e29822e">NORM_MINMAX</a>);</div><div class="line">    <a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">imwrite</a>(<span class="stringliteral">&quot;filter.jpg&quot;</span>, H);</div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> fftshift(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputImg, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; outputImg)</div><div class="line">{</div><div class="line">    outputImg = inputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>();</div><div class="line">    <span class="keywordtype">int</span> cx = outputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> / 2;</div><div class="line">    <span class="keywordtype">int</span> cy = outputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> / 2;</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q0(outputImg, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, cx, cy));</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q1(outputImg, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, 0, cx, cy));</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q2(outputImg, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, cy, cx, cy));</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q3(outputImg, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, cy, cx, cy));</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> tmp;</div><div class="line">    q0.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(tmp);</div><div class="line">    q3.copyTo(q0);</div><div class="line">    tmp.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(q3);</div><div class="line">    q1.copyTo(tmp);</div><div class="line">    q2.copyTo(q1);</div><div class="line">    tmp.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(q2);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> filter2DFreq(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputImg, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; outputImg, <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; H)</div><div class="line">{</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> planes[2] = { <a class="code" href="../../df/dfc/classcv_1_1Mat__.html">Mat_&lt;float&gt;</a>(inputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>()), <a class="code" href="../../d3/d63/classcv_1_1Mat.html#a0b57b6a326c8876d944d188a46e0f556">Mat::zeros</a>(inputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>) };</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> complexI;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4">merge</a>(planes, 2, complexI);</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">dft</a>(complexI, complexI, <a class="code" href="../../d2/de8/group__core__array.html#ggaf4dde112b483b38175621befedda1f1ca74746fb171aa4bfc08ace28d73f52375">DFT_SCALE</a>);</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> planesH[2] = { <a class="code" href="../../df/dfc/classcv_1_1Mat__.html">Mat_&lt;float&gt;</a>(H.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>()), <a class="code" href="../../d3/d63/classcv_1_1Mat.html#a0b57b6a326c8876d944d188a46e0f556">Mat::zeros</a>(H.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>) };</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> complexH;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4">merge</a>(planesH, 2, complexH);</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> complexIH;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga3ab38646463c59bf0ce962a9d51db64f">mulSpectrums</a>(complexI, complexH, complexIH, 0);</div><div class="line"></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gaa708aa2d2e57a508f968eb0f69aa5ff1">idft</a>(complexIH, complexIH);</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga0547c7fed86152d7e9d0096029c8518a">split</a>(complexIH, planes);</div><div class="line">    outputImg = planes[0];</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> synthesizeFilterH(<a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputOutput_H, <a class="code" href="../../db/d4e/classcv_1_1Point__.html">Point</a> center, <span class="keywordtype">int</span> radius)</div><div class="line">{</div><div class="line">    <a class="code" href="../../db/d4e/classcv_1_1Point__.html">Point</a> c2 = center, c3 = center, c4 = center;</div><div class="line">    c2.<a class="code" href="../../db/d4e/classcv_1_1Point__.html#a157337197338ff199e5df1a393022f15">y</a> = inputOutput_H.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> - center.<a class="code" href="../../db/d4e/classcv_1_1Point__.html#a157337197338ff199e5df1a393022f15">y</a>;</div><div class="line">    c3.x = inputOutput_H.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> - center.<a class="code" href="../../db/d4e/classcv_1_1Point__.html#a4c96fa7bdbfe390be5ed356edb274ff3">x</a>;</div><div class="line">    c4 = <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(c3.x,c2.<a class="code" href="../../db/d4e/classcv_1_1Point__.html#a157337197338ff199e5df1a393022f15">y</a>);</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">circle</a>(inputOutput_H, center, radius, 0, -1, 8);</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">circle</a>(inputOutput_H, c2, radius, 0, -1, 8);</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">circle</a>(inputOutput_H, c3, radius, 0, -1, 8);</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">circle</a>(inputOutput_H, c4, radius, 0, -1, 8);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// Function calculates PSD(Power spectrum density) by fft with two flags</span></div><div class="line"><span class="comment">// flag = 0 means to return PSD</span></div><div class="line"><span class="comment">// flag = 1 means to return log(PSD)</span></div><div class="line"><span class="comment"></span><span class="keywordtype">void</span> calcPSD(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; inputImg, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; outputImg, <span class="keywordtype">int</span> flag)</div><div class="line">{</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> planes[2] = { <a class="code" href="../../df/dfc/classcv_1_1Mat__.html">Mat_&lt;float&gt;</a>(inputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>()), <a class="code" href="../../d3/d63/classcv_1_1Mat.html#a0b57b6a326c8876d944d188a46e0f556">Mat::zeros</a>(inputImg.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>) };</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> complexI;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4">merge</a>(planes, 2, complexI);</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">dft</a>(complexI, complexI);</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga0547c7fed86152d7e9d0096029c8518a">split</a>(complexI, planes);            <span class="comment">// planes[0] = Re(DFT(I)), planes[1] = Im(DFT(I))</span></div><div class="line"></div><div class="line">    planes[0].<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa5d20fc86d41d59e4d71ae93daee9726">at</a>&lt;<span class="keywordtype">float</span>&gt;(0) = 0;</div><div class="line">    planes[1].<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa5d20fc86d41d59e4d71ae93daee9726">at</a>&lt;<span class="keywordtype">float</span>&gt;(0) = 0;</div><div class="line"></div><div class="line">    <span class="comment">// compute the PSD = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)^2</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> imgPSD;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3">magnitude</a>(planes[0], planes[1], imgPSD);        <span class="comment">//imgPSD = sqrt(Power spectrum density)</span></div><div class="line">    <a class="code" href="../../d7/dcc/group__core__utils__softfloat.html#ga8bc36646a43b82baa15f151a973fb0c5">pow</a>(imgPSD, 2, imgPSD);                         <span class="comment">//it needs ^2 in order to get PSD</span></div><div class="line">    outputImg = imgPSD;</div><div class="line"></div><div class="line">    <span class="comment">// logPSD = log(1 + PSD)</span></div><div class="line">    <span class="keywordflow">if</span> (flag)</div><div class="line">    {</div><div class="line">        <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> imglogPSD;</div><div class="line">        imglogPSD = imgPSD + <a class="code" href="../../d1/da0/classcv_1_1Scalar__.html#ac1509a4b8454fe7fe29db069e13a2e6f">Scalar::all</a>(1);</div><div class="line">        <a class="code" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">log</a>(imglogPSD, imglogPSD);</div><div class="line">        outputImg = imglogPSD;</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment --><h2>Explanation </h2>
<p>Periodic noise reduction by frequency domain filtering consists of power spectrum density calculation (for the noise spikes visual detection), notch reject filter synthesis and frequency filtering: </p><div class="fragment"><div class="line">    <span class="comment">// it needs to process even image only</span></div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a> roi = <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, imgIn.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> &amp; -2, imgIn.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> &amp; -2);</div><div class="line">    imgIn = imgIn(roi);</div><div class="line"></div><div class="line">    <span class="comment">// PSD calculation (start)</span></div><div class="line">    Mat imgPSD;</div><div class="line">    calcPSD(imgIn, imgPSD);</div><div class="line">    fftshift(imgPSD, imgPSD);</div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize</a>(imgPSD, imgPSD, 0, 255, <a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa9f0c1c342a18114d47b516a88e29822e">NORM_MINMAX</a>);</div><div class="line">    <span class="comment">// PSD calculation (stop)</span></div><div class="line"></div><div class="line">    <span class="comment">//H calculation (start)</span></div><div class="line">    Mat H = Mat(roi.size(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>(1));</div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">int</span> r = 21;</div><div class="line">    synthesizeFilterH(H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(705, 458), r);</div><div class="line">    synthesizeFilterH(H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(850, 391), r);</div><div class="line">    synthesizeFilterH(H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(993, 325), r);</div><div class="line">    <span class="comment">//H calculation (stop)</span></div><div class="line">    <span class="comment">// filtering (start)</span></div><div class="line">    Mat imgOut;</div><div class="line">    fftshift(H, H);</div><div class="line">    filter2DFreq(imgIn, imgOut, H);</div><div class="line">    <span class="comment">// filtering (stop)</span></div></div><!-- fragment --><p> A function calcPSD() calculates power spectrum density of an image: </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> calcPSD(<span class="keyword">const</span> Mat&amp; inputImg, Mat&amp; outputImg, <span class="keywordtype">int</span> flag)</div><div class="line">{</div><div class="line">    Mat planes[2] = { Mat_&lt;float&gt;(inputImg.clone()), Mat::zeros(inputImg.size(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>) };</div><div class="line">    Mat complexI;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4">merge</a>(planes, 2, complexI);</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">dft</a>(complexI, complexI);</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga0547c7fed86152d7e9d0096029c8518a">split</a>(complexI, planes);            <span class="comment">// planes[0] = Re(DFT(I)), planes[1] = Im(DFT(I))</span></div><div class="line"></div><div class="line">    planes[0].at&lt;<span class="keywordtype">float</span>&gt;(0) = 0;</div><div class="line">    planes[1].at&lt;<span class="keywordtype">float</span>&gt;(0) = 0;</div><div class="line"></div><div class="line">    <span class="comment">// compute the PSD = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)^2</span></div><div class="line">    Mat imgPSD;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3">magnitude</a>(planes[0], planes[1], imgPSD);        <span class="comment">//imgPSD = sqrt(Power spectrum density)</span></div><div class="line">    <a class="code" href="../../d7/dcc/group__core__utils__softfloat.html#ga8bc36646a43b82baa15f151a973fb0c5">pow</a>(imgPSD, 2, imgPSD);                         <span class="comment">//it needs ^2 in order to get PSD</span></div><div class="line">    outputImg = imgPSD;</div><div class="line"></div><div class="line">    <span class="comment">// logPSD = log(1 + PSD)</span></div><div class="line">    <span class="keywordflow">if</span> (flag)</div><div class="line">    {</div><div class="line">        Mat imglogPSD;</div><div class="line">        imglogPSD = imgPSD + Scalar::all(1);</div><div class="line">        <a class="code" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">log</a>(imglogPSD, imglogPSD);</div><div class="line">        outputImg = imglogPSD;</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment --><p> A function synthesizeFilterH() forms a transfer function of an ideal circular shape notch reject filter according to a center frequency and a radius: </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> synthesizeFilterH(Mat&amp; inputOutput_H, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a> center, <span class="keywordtype">int</span> radius)</div><div class="line">{</div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a> c2 = center, c3 = center, c4 = center;</div><div class="line">    c2.<a class="code" href="../../db/d4e/classcv_1_1Point__.html#a157337197338ff199e5df1a393022f15">y</a> = inputOutput_H.rows - center.y;</div><div class="line">    c3.x = inputOutput_H.cols - center.x;</div><div class="line">    c4 = <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(c3.x,c2.y);</div><div class="line">    <a class="code" href="../../d9/db7/group__datasets__gr.html#gga610754124ced68d1f05760b5948fbb76a6f0d8b2d9e3e947b2a5c1eff9e81ee95">circle</a>(inputOutput_H, center, radius, 0, -1, 8);</div><div class="line">    <a class="code" href="../../d9/db7/group__datasets__gr.html#gga610754124ced68d1f05760b5948fbb76a6f0d8b2d9e3e947b2a5c1eff9e81ee95">circle</a>(inputOutput_H, c2, radius, 0, -1, 8);</div><div class="line">    <a class="code" href="../../d9/db7/group__datasets__gr.html#gga610754124ced68d1f05760b5948fbb76a6f0d8b2d9e3e947b2a5c1eff9e81ee95">circle</a>(inputOutput_H, c3, radius, 0, -1, 8);</div><div class="line">    <a class="code" href="../../d9/db7/group__datasets__gr.html#gga610754124ced68d1f05760b5948fbb76a6f0d8b2d9e3e947b2a5c1eff9e81ee95">circle</a>(inputOutput_H, c4, radius, 0, -1, 8);</div><div class="line">}</div></div><!-- fragment --><p> A function filter2DFreq() filters an image in the frequency domain. The functions fftshift() and filter2DFreq() are copied from the tutorial <a class="el" href="../../de/d3c/tutorial_out_of_focus_deblur_filter.html">Out-of-focus Deblur Filter</a>.</p>
<h2>Result </h2>
<p>The figure below shows an image heavily corrupted by periodical noise of various frequencies. </p><div class="image">
<img src="../../period_input.jpg" alt="period_input.jpg"/>
<div class="caption">
Image corrupted by periodic noise</div></div>
<p> The noise components are easily seen as bright dots (spikes) in the Power spectrum density shown in the figure below. </p><div class="image">
<img src="../../period_psd.jpg" alt="period_psd.jpg"/>
<div class="caption">
Power spectrum density showing periodic noise</div></div>
<p> The figure below shows a notch reject filter with an appropriate radius to completely enclose the noise spikes. </p><div class="image">
<img src="../../period_filter.jpg" alt="period_filter.jpg"/>
<div class="caption">
Notch reject filter</div></div>
<p> The result of processing the image with the notch reject filter is shown below. </p><div class="image">
<img src="../../period_output.jpg" alt="period_output.jpg"/>
<div class="caption">
Result of filtering</div></div>
<p> The improvement is quite evident. This image contains significantly less visible periodic noise than the original image.</p>
<p>You can also find a quick video demonstration of this filtering idea on <a href="https://youtu.be/Qne51TcWwAc">YouTube</a>. </p><div align='center'><iframe title='Video' width='560' height='349' src='https://www.youtube.com/embed/Qne51TcWwAc?rel=0' frameborder='0' align='middle' allowfullscreen></iframe></div> </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:36 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
